package com.alks.function.service.impl.stock;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.enums.ResultCodeEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.PcMtlStockDto;
import com.alks.function.data.dto.PcMtlStockInDto;
import com.alks.function.data.dto.PcMtlStockOutDto;
import com.alks.function.data.request.operate.material.*;
import com.alks.function.data.request.operate.materialIn.MtlBIStorageReq;
import com.alks.function.data.request.stock.InventoryLocFil;
import com.alks.function.data.request.stock.PcMtlStockRequest;
import com.alks.function.mapper.PcMtlStockMapper;
import com.alks.function.service.PcMtlStockService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.RedisFormatEnum.PUT_PUR_LENGTH;

/**
 * @author:xxxxx
 * @create: 2023-06-29 09:55
 * @Description: 库存资料
 */
@Service
@Slf4j
public class PcMtlStockServiceImpl extends ServiceImpl<PcMtlStockMapper, PcMtlStock> implements PcMtlStockService {
    @Autowired
    PcMtlStockMapper pcMtlStockMapper;
    @Override
    public ResponseInfo pcMtlStockList(PcMtlStockRequest request) {
        if (request == null){
            return ResponseInfo.error(ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getMessage(), ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getCode());
        }
        if (request.getPageNum() == null || request.getPageSize() == null) {
            request.setPageNum(1);
            request.setPageSize(10);
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize(),false);
        PcMtlStockDto dto = new PcMtlStockDto();
        List<PcMtlStock> pcMtlStocks = pcMtlStockMapper.pcMtlStockList(request);
        dto.setList(pcMtlStocks);
        Long total = pcMtlStockMapper.pcMtlStockTotal(request);
        dto.setTotal(total);
        BigDecimal stocks = pcMtlStockMapper.getStocks(request);
        if (stocks == null){
            stocks = new BigDecimal(0);
        }
        dto.setStocks(stocks.setScale(2,RoundingMode.HALF_UP));
        return ResponseInfo.ok(dto);
    }

    @Override
    public ResponseInfo pcMtlStockInOutList(String mtlNo) {
        if (mtlNo == null  ){
            return ResponseInfo.error(ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getMessage(), ResultCodeEnum.LOGIN_CONFIG_IS_NULL.getCode());
        }
        List<PcMtlStockIn> pcMtlStockIns = pcMtlStockMapper.pcMtlStockIn(mtlNo);
        PcMtlStockInDto in = new PcMtlStockInDto();
        in.setList(pcMtlStockIns);
        List<PcMtlStockOut> pcMtlStockOuts = pcMtlStockMapper.pcMtlStockOut(mtlNo);
        PcMtlStockOutDto out = new PcMtlStockOutDto();
        out.setList(pcMtlStockOuts);
        HashMap<String, Object> dto = new HashMap<>();
        dto.put("inStockMsg",in);
        dto.put("outStockMsg",out);
        return ResponseInfo.ok(dto);
    }

    @Override
    public ResponseInfo pcMtlStockCondition() {
        HashMap<String, List<Map<String,String>>> map = new HashMap<>();
        List<Map<String,String>> list = pcMtlStockMapper.pcMtlStockCondition();
        map.put("type",list);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo wareHouseList(InventoryLocFil request) {
        return ResponseInfo.ok(pcMtlStockMapper.wareHouseList(request));
    }

    @Override
    public ResponseInfo insertHouse(InventoryLocFil request) {
        String username = UserIdThread.get().getUserName();
        List<InventoryLocFil> list = pcMtlStockMapper.wareHouseList(request);
        if (!list.isEmpty()){
            return ResponseInfo.error("该条数据已存在、请重新插入1条");
        }
        request.setCompanyId(UserIdThread.get().getCompanyId());
        pcMtlStockMapper.insertHouse(request,username);
        return ResponseInfo.ok("插入成功");
    }

    @Override
    @AutoPageAop
    public ResponseInfo mtlBIStorageList(MtlBIStorageReq req) {
        Map<String,Object> map = new HashMap<>();
        List<MtlBIStorageRep> list = pcMtlStockMapper.mtlBIStorageList(req);
        BigDecimal inTotal = pcMtlStockMapper.mtlBIStorageInTotal(req);
        Page<MtlBIStorageRep> page = (Page<MtlBIStorageRep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        map.put("inTotal",inTotal);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo deleteBIStorage(MtlBIStorageRep req) {
        int num = pcMtlStockMapper.deleteBIStorage(req);
        if (num<=0){
            return ResponseInfo.error("删除失败");
        }
        return ResponseInfo.ok("删除成功");
    }

    @Override
    @AutoPageAop
    public ResponseInfo chooseMtlInList(MaterialOtherChoReq req) {
        Map<String,Object> map = new HashMap<>();
        List<SdMtlNewKfRep> list = pcMtlStockMapper.chooseMtlInList(req);
        Page<SdMtlNewKfRep> page = (Page<SdMtlNewKfRep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo insertMtlInList(List<SdMtlNewKfRep> list) {
        String username = UserIdThread.get().getLoginName();
        list.forEach(x->x.setCompanyId(UserIdThread.get().getCompanyId()));
        int num = pcMtlStockMapper.insertIntoTemp(list,username);
        return ResponseInfo.ok("插入成功");
    }

    @Override
    public ResponseInfo mtlOtherList() {
        String name = UserIdThread.get().getLoginName();
        Map<String,Object> map = new HashMap<>();
        List<SdMtlOtherTempRep> list = pcMtlStockMapper.mtlOtherList(name);
        Set<Map<String,String>> sets = pcMtlStockMapper.getSdmtl();
        loop:for (Map<String, String> set : sets) {
            for (SdMtlOtherTempRep rep : list) {
                if (rep.getMtlNo() == null || rep.getMtlNo().isEmpty()){break;}
                if (set.get("TYPE_NO").equals(rep.getMtlNo().substring(0,4))){
                    rep.setTypeName(set.get("TYPE_NAME"));
                }else if (set.get("TYPE_NO").equals(set.get(rep.getMtlNo().substring(0,2)))){
                    rep.setTypeName(set.get("TYPE_NAME"));
                }else if (set.get("TYPE_NO").equals(set.get(rep.getMtlNo().substring(0,1)))){
                    rep.setTypeName(set.get("TYPE_NAME"));
                }
            }
            int count = (int) list.stream().filter(x -> x.getTypeName() == null).count();
            if (count<=0){
                break loop;
            }
        }
        map.put("list",list);
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo deleteByTemp() {
        String name = UserIdThread.get().getLoginName();
        List<SdMtlOtherTempRep> list = pcMtlStockMapper.mtlOtherList(name);
        if (list.isEmpty()){
            return ResponseInfo.ok("删除成功");
        }
        int num = pcMtlStockMapper.deleteByTemp(name);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    @AutoPageAop
    public ResponseInfo mtlDetailList(MaterialOtherDetailReq req) {
        Map<String,Object> map = new HashMap<>();
        List<SdMtlOtherTempDetailRep> list = pcMtlStockMapper.mtlDetailList(req);
        Page<SdMtlOtherTempDetailRep> page = (Page<SdMtlOtherTempDetailRep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Autowired
    RedisService redisService;
    @Override
    public ResponseInfo cOtherDetailList(CreMtlOtherDetailReq req) {
        //生成入库单号
        String slipNo = "XYRK";
        String format = new SimpleDateFormat("yyyyMM").format(new Date());
        slipNo = slipNo+format;
        RedisAtomicInteger ato = new RedisAtomicInteger(slipNo,redisService.getConnectionFactory());
        int increment = ato.getAndIncrement();
        String num = String.format("%0" + PUT_PUR_LENGTH.getValue() + "d", increment);
        slipNo=slipNo+num;
        String name = UserIdThread.get().getLoginName();
        for (SdMtlOtherTempRep rep : req.getList()) {
            rep.setCompanyId(UserIdThread.get().getCompanyId());
            if (rep.getQty()==null||rep.getAreaNo()==null||rep.getAreaNo().isEmpty()){
                return ResponseInfo.error("入库数量和库存不能为空");
            }
        }
        int count = pcMtlStockMapper.cOtherDetailList(req,name,slipNo);
        //获取用户id
        pcMtlStockMapper.deleteByTemp(name);
        //删除选择材料
        return ResponseInfo.ok("生成成功");
    }

    @Override
    public ResponseInfo dOtherDetail(SdMtlOtherTempDetailRep req) {
        int num = pcMtlStockMapper.dOtherDetail(req);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    public ResponseInfo deleteHouse(InventoryLocFil request) {
        pcMtlStockMapper.deleteHouse(request);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    public ResponseInfo outMtlList(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        Map<String,Object> map = new HashMap<>();
        List<PcMtlOut1Rep> list = pcMtlStockMapper.outMtlList();
        BigDecimal outTotal = pcMtlStockMapper.outMtlListOutQtyTotal();
        Page<PcMtlOut1Rep> page = (Page<PcMtlOut1Rep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        map.put("outTotal",outTotal);
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo chooseMtlOtherList(MaterialOtherChoReq req) {
        Map<String,Object> map = new HashMap<>();
        List<PcMtlOtherOut2Rep> list = pcMtlStockMapper.chooseMtlOtherList(req);
        Page<PcMtlOtherOut2Rep> page = (Page<PcMtlOtherOut2Rep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo otherMtlOuts(List<PcMtlOtherOut2Rep> req) {
        String name = UserIdThread.get().getLoginName();
        for (PcMtlOtherOut2Rep pcMtlOtherOut2Rep : req) {
            pcMtlOtherOut2Rep.setCompanyId(UserIdThread.get().getCompanyId());
            if (pcMtlOtherOut2Rep.getStkQty().doubleValue() <= 0){
                return ResponseInfo.error("库存不能为0，请检查选择的材料库存");
            }
        }
        pcMtlStockMapper.otherMtlOuts(req,name);
        return ResponseInfo.ok("插入成功");
    }

    @Override
    public ResponseInfo otherMtlDetailList() {
        List<OtherMtlDetailOutRep> list = pcMtlStockMapper.otherMtlDetailList(UserIdThread.get().getLoginName());
        return ResponseInfo.ok(list);
    }

    @Override
    @Transactional
    public ResponseInfo creOtherMtlSlip(OtherMtlDetailOutListReq req) {
        //获取用户id
        String name = UserIdThread.get().getLoginName();
        //生成出库单号
        //RXCK
        String slipNo = "RXCK";
        String format = new SimpleDateFormat("yyyyMM").format(new Date());
        slipNo = slipNo+format;
        RedisAtomicInteger ato = new RedisAtomicInteger(slipNo,redisService.getConnectionFactory());
        int increment = ato.getAndIncrement();
        String num = String.format("%0" + PUT_PUR_LENGTH.getValue() + "d", increment);
        slipNo=slipNo+num;
        //判断出库数量是否小于库存数量 且指令不能为空
        List<OtherMtlDetailOutRep> list = req.getList();
        for (OtherMtlDetailOutRep rep : list) {
            if (rep.getLotNo() == null || rep.getLotNo().isEmpty() ||
                    rep.getOutQty() == null || rep.getOutQty().doubleValue() == 0 ||
                    rep.getOutQty().doubleValue() > rep.getQty().doubleValue()) {
                return ResponseInfo.error("指令号以及出库数量不能大于库存数量、且出库数量不能为空");
            }
        }
        req.getList().forEach(x->x.setCompanyId(UserIdThread.get().getCompanyId()));
        //将生成的订单号存放进 出库表中
        pcMtlStockMapper.creOtherMtlSlip(req,slipNo,name);
        //将出库的数量记录在库存表中 out_qty 且对应相应的stk_qty
        pcMtlStockMapper.reduceStock(req);
        //删除所有临时表中的数据
        pcMtlStockMapper.deleteByTemp(name);
        return ResponseInfo.ok("生成成功");
    }

    @Override
    @AutoPageAop
    public ResponseInfo otherDetails(MtlOther2Req req) {
        Map<String,Object> map = new HashMap<>();
        List<MtlOtherDetailOut1Rep> list = pcMtlStockMapper.otherDetails(req);
        Page<MtlOtherDetailOut1Rep> page = (Page<MtlOtherDetailOut1Rep>) list;
        map.put("list",list);
        map.put("total",page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo deleteByOtherDetail(MtlOtherDetailOut1Rep rep) {
        pcMtlStockMapper.deleteByOtherDetail(rep);
        return ResponseInfo.ok("删除成功");
    }

    @Override
    public void downloadMtlSto(HttpServletResponse response, PcMtlStockRequest request) throws IOException {
        List<PcMtlStock> pcMtlStocks = pcMtlStockMapper.pcMtlStockList(request);
        ExcelUtils.creatByTemplate(response,"材料库存模板.xls",pcMtlStocks);
    }

    @Override
    public ResponseInfo scanInPcMtlIn(String slipNo) {
        //查询该单号是否入库
        Integer num = pcMtlStockMapper.getSlipByPre(slipNo);
        pcMtlStockMapper.deleteByTemp(UserIdThread.get().getLoginName());
        if (num<=0){
            return ResponseInfo.error("没有该单号");
        }
        String name = UserIdThread.get().getLoginName();
        Integer inMtlNum = pcMtlStockMapper.getBySlipNo(slipNo);
        Integer preSize = pcMtlStockMapper.getPreSlipSize(slipNo);
        if (inMtlNum>=preSize){
            return ResponseInfo.error("该订单已入库");
        }
        //写入临时表
        pcMtlStockMapper.insertIntoPcScanTemp(slipNo,name);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo getScanInSlipTemp() {
        List<ScanTheDocumentInformation> list = pcMtlStockMapper.getScanInSlipTemp(UserIdThread.get().getLoginName());
        return ResponseInfo.ok(list);
    }

    @Override
    public ResponseInfo deleteSlipInTemp() {
        pcMtlStockMapper.deleteByTemp(UserIdThread.get().getLoginName());
        return ResponseInfo.ok();
    }

    @Override
    @Transactional
    public ResponseInfo genericSlipNo(List<ScanTheDocumentInformation> list) {
        String string = redisService.barcodeCreat("RXRA", 6);
        AtomicReference<Integer> i = new AtomicReference<>(0);
        list.forEach(x->{x.setSendNo(string);x.setBarcode(String.format(string+"%2d", i.getAndSet(i.get() + 1)));});
        pcMtlStockMapper.deleteByTempList(UserIdThread.get().getLoginName(),list);
        list.forEach(x->x.setCompanyId(UserIdThread.get().getCompanyId()));
        pcMtlStockMapper.insetIntoPcMtlIn(list,UserIdThread.get().getUserName());
        //查询判断添加还是新增
        for (ScanTheDocumentInformation req :list){
            Integer num = pcMtlStockMapper.getMtlByStock(req);
            req.setCompanyId(UserIdThread.get().getCompanyId());
            if (num>0) pcMtlStockMapper.updatePcMtlStock(req); else pcMtlStockMapper.insertIntoPcMtlStock(req);
        }
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo printPcMtlIn(List<String> sendNos) {
        pcMtlStockMapper.updatePcMtlIn(sendNos);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo scanSlipByLotNo(String lotNo) {
        pcMtlStockMapper.deleteByTemp(UserIdThread.get().getLoginName());
        Integer i = pcMtlStockMapper.scanSlipByLotNo(UserIdThread.get().getLoginName(), lotNo);
        if (i<=0) return ResponseInfo.error("该样品单未做备料");
        return ResponseInfo.ok("");
    }

    @Override
    public ResponseInfo getScanSlipByLotNo() {
        List<ScanOutDetail> list = pcMtlStockMapper.getScanSlipByLotNo(UserIdThread.get().getLoginName());
        String lotNo = "";
        if (!list.isEmpty()){
            lotNo = list.get(0).getLotNo();
            ScanOutDetail scan = pcMtlStockMapper.getPcPurDetail(lotNo);
            list.forEach(x->{x.setUserId(scan.getUserId());x.setSysDate(scan.getSysDate());});
        }
        return ResponseInfo.ok(list);
    }

    @Override
    @Transactional
    public ResponseInfo createOutSlipNo(List<ScanOutDetail> list) {
        String name = UserIdThread.get().getUserName();
        String slipNo  = redisService.barcodeCreatTwo("RXCA", 4);
        log.info(slipNo);
        list.forEach(x->x.setBarcode(redisService.barcodeCreatAdd(slipNo, 2)));
        list.forEach(x->x.setCompanyId(UserIdThread.get().getCompanyId()));
        List<ScanOutDetail> collect = list.stream().filter(x -> x.getOutQty() != null && x.getOutQty().doubleValue() > 0).collect(Collectors.toList());
        pcMtlStockMapper.createOutSlipNo(collect,slipNo,name);
        for (ScanOutDetail scan : collect) {
            if (scan.getOutQty() ==null || scan.getOutQty().doubleValue() == 0) continue;
            pcMtlStockMapper.updateDPcMtlStock(scan);
        }
        //TODO 修改pcpurdetail 出库数量
//        pcMtlStockMapper.updatePcPurDetail(list);
        pcMtlStockMapper.deleteByTemp(UserIdThread.get().getLoginName());
        //库存减去出库数量
        return ResponseInfo.ok();
    }
}
